15. Первая 3Д игра. Часть 5 – оптимизация кода Но это ещё не всё… Дальше мы возьмём готовые куски кода, и создадим из них функции… (вот где всё самое клёвое-то начинается J!!!) Для начала предлагаю сделать функцию, создающую кубики. Назовём её, например, CreateWalls(tn), в скобки которой будем указывать, сколько кубиков нам надо создать! (Вот для чего нам нужны были списки J)… Функции (как вы помните) нужно вставлять в конце кода, после команды End. Как мы её сделаем? Да просто вырежем весь кусок кода, в котором мы создаём кубики и стены, и засунем в функцию (поменяв заодно цифру 29 на tn – переменную, в которой будет содержаться число, введённое в функцию): Function CreateWalls(tn) For i=0 To tn w.Walls = New Walls w\model=CreateCube() Repeat PositionEntity w\model,Rnd(-40,40),0,Rnd(-40,40) Until Abs(EntityX(w\model))>10 Or Abs(EntityZ(w\model))>10 EntityType w\model, TypeWalls EntityColor w\model,255,0,0 Next w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,-50,0,0 FitMesh w\model,-1,-1,-50,2,3,100 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,50,0,0 FitMesh w\model,-1,-1,-50,2,3,100 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,0,0,-50 FitMesh w\model,-50,-1,-1,100,3,2 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,0,0,50 FitMesh w\model,-50,-1,-1,100,3,2 End Function | … а вместо него напишем: Дальше предлагаю создать функцию для того, чтобы ставить цилиндр в случайное место и заодно проверять его – вырежем то, что у нас в главном цикле, где цилиндр устанавливается в случайное место, и проверяется его пересечение с кубиками: Function PositionTarget() Repeat inter=False PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40) For w.Walls = Each Walls If MeshesIntersect(Target, w\model) inter=True Next Until inter=False End Function | Ну а вместо этого куска кода вставим вызов этой функции – т.е. так: If EntityCollided (Player,TypeTarget) PositionTarget() UpdateWorld Score=Score+1 Speed=Speed+.01 EndIf | Заодно, заменим строчку в самом начале, когда мы создаём цилиндр: PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40) | …на: (а то я забыл в самом начале указать проверку на пересечение с кубиками, и получалось так, что в самом начале цилиндр мог находиться наполовину в кубе J) Так продолжим нашу вырезательную деятельность… Теперь засунем в функцию команды создания игрока Function CreatePlayer() Player=CreateSphere() Plac=CreateCone(8) RotateMesh Plac,-90,0,0 ScaleMesh Plac,1,1,1.2 PositionMesh Plac,0,0,-1.5 AddMesh Plac,Player EntityType Player, TypePlayer EntityColor Player,0,255,0 FreeEntity Plac End Function | А наверху у нас останется: Global Player CreatePlayer() | Также сделаем функцию для создания цилиндра Function CreateTarget() Target=CreateCylinder() PositionTarget() EntityColor Target,255,215,0 EntityType Target,TypeTarget End Function | Ну, а наверху, мы напишем… Global Target CreateTarget() | Не забудьте обозначить переменную Target как Global – иначе функция не «увидит» её… И функцию для создания камеры и света Function CreateEnv() cam=CreateCamera() PositionEntity cam,0,40,0 TurnEntity cam,90,0,0 lit=CreateLight() TurnEntity lit,70,70,0 End Function | Ну, и наверху, не забыв обозначить переменные cam и lit как Global, напишем Global cam Global lit CreateEnv() | Теперь, возьмём все команды в главном цикле (кроме команды Flip), и сделаем из них… правильно Функцию! А как вы догадались? J… Function UpdateGame() MoveEntity Player,0,0,Speed# If KeyDown(203) TurnEntity Player,0,3,0 If KeyDown(205) TurnEntity Player,0,-3,0 PointEntity cam,Player If EntityCollided (Player,TypeTarget) PositionTarget() UpdateWorld Score=Score+1 Speed=Speed+.01 EndIf If EntityCollided (Player,TypeWalls) End UpdateWorld RenderWorld Color 255,215,0 Text 320,10,"Score : "+Score,True,True End Function | И весь главный цикл у нас будет представлять: Repeat UpdateGame() Flip Until KeyHit(1) | А команды инициализации после некоторой оптимизации и расставления по местам будут выглядеть так: SeedRnd MilliSecs() Type Walls Field model End Type Const TypePlayer=1,TypeWalls=2,TypeTarget=3 Global Speed#=.1,Score=0 Global Player Global Target Global cam Global lit Graphics3D 640,480,16,1 SetBuffer BackBuffer() CreatePlayer() CreateWalls(29) CreateTarget() CreateEnv() Collisions TypePlayer,TypeWalls,2,2 Collisions TypePlayer,TypeTarget,2,2 | И последнюю функцию мы создадим сами. Она будет очистит из памяти все объекты которые мы тут создавали… Function FreeGame() ClearCollisions FreeEntity cam FreeEntity lit FreeEntity Player FreeEntity Target For w.Walls=Each Walls FreeEntity w\model Delete w Next Speed#=.1 Score=0 End Function | Обратите внимание на то, как удаляются списки. Сначала удаляются все объекты, занимающие память, а потом указатель на элемент списка… ну, понятно, короче J… И заодно вызовем эту функцию как раз перед командой End. (ну это надеюсь сами сделаете) Вот так выглядит наш код после оптимизации, (или офункциации J): SeedRnd MilliSecs() Type Walls Field model End Type Const TypePlayer=1,TypeWalls=2,TypeTarget=3 Global Speed#=.1,Score=0 Global Player Global Target Global cam Global lit Graphics3D 640,480,16,1 SetBuffer BackBuffer() CreatePlayer() CreateWalls(29) CreateTarget() CreateEnv() Collisions TypePlayer,TypeWalls,2,2 Collisions TypePlayer,TypeTarget,2,2 ;******************* ;Main Cycle ;******************* Repeat UpdateGame() Flip Until KeyHit(1) FreeGame() End ;******************* ;Functions ;******************* Function CreateWalls(tn) For i=0 To tn w.Walls = New Walls w\model=CreateCube() Repeat PositionEntity w\model,Rnd(-40,40),0,Rnd(-40,40) Until Abs(EntityX(w\model))>10 Or Abs(EntityZ(w\model))>10 EntityType w\model, TypeWalls EntityColor w\model,255,0,0 Next w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,-50,0,0 FitMesh w\model,-1,-1,-50,2,3,100 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,50,0,0 FitMesh w\model,-1,-1,-50,2,3,100 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,0,0,-50 FitMesh w\model,-50,-1,-1,100,3,2 w.Walls = New Walls w\model=CreateCube() EntityColor w\model,100,20,0 EntityType w\model,TypeWalls PositionEntity w\model,0,0,50 FitMesh w\model,-50,-1,-1,100,3,2 End Function Function PositionTarget() Repeat inter=False PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40) For w.Walls = Each Walls If MeshesIntersect(Target, w\model) inter=True Next Until inter=False End Function Function CreatePlayer() Player=CreateSphere() Plac=CreateCone(8) RotateMesh Plac,-90,0,0 ScaleMesh Plac,1,1,1.2 PositionMesh Plac,0,0,-1.5 AddMesh Plac,Player EntityType Player, TypePlayer EntityColor Player,0,255,0 FreeEntity Plac End Function Function CreateTarget() Target=CreateCylinder() PositionTarget() EntityColor Target,255,215,0 EntityType Target,TypeTarget End Function Function CreateEnv() cam=CreateCamera() PositionEntity cam,0,40,0 TurnEntity cam,90,0,0 lit=CreateLight() TurnEntity lit,70,70,0 End Function Function UpdateGame() MoveEntity Player,0,0,Speed# If KeyDown(203) TurnEntity Player,0,3,0 If KeyDown(205) TurnEntity Player,0,-3,0 PointEntity cam,Player If EntityCollided (Player,TypeTarget) PositionTarget() UpdateWorld Score=Score+1 Speed=Speed+.01 EndIf If EntityCollided (Player,TypeWalls) End UpdateWorld RenderWorld Color 255,215,0 Text 320,10,"Score : "+Score,True,True End Function Function FreeGame() ClearCollisions FreeEntity cam FreeEntity lit FreeEntity Player FreeEntity Target For w.Walls=Each Walls FreeEntity w\model Delete w Next Speed#=.1 Score=0 End Function | | Оглавление: 0. Введение 1. В начале была Тьма 2. Есть ли жизнь в DirectX 3. Свобода и Власть 3Д (0) 4. Свобода и Власть 3Д (1) 5. 2Д в 3Д 6. Трёхмерный курсор 7. Родительская зависимость или Привязки 8. Фишки с привязками 9. Коллизион Детекшн или как устроен мир… 10. Первая 3Д игра. Часть 0 – основы движка 11. Первая 3Д игра. Часть 1 – разработка движка 12. Первая 3Д игра. Часть 2 – устранение багов 13. Первая 3Д игра. Часть 3 – внешний вид 14. Первая 3Д игра. Часть 4 – от массива к спискам 15. Первая 3Д игра. Часть 5 – оптимизация кода 16. Первая 3Д игра. Часть 6 – завершение 17. Выведение |